home *** CD-ROM | disk | FTP | other *** search
/ SGI Freeware 1999 August / SGI Freeware 1999 August.iso / dist / fw_emacs.idb / usr / freeware / share / emacs / 19.34 / lisp / apropos.el.z / apropos.el
Encoding:
Text File  |  1998-10-28  |  19.9 KB  |  603 lines

  1. ;;; apropos.el --- apropos commands for users and programmers.
  2.  
  3. ;; Copyright (C) 1989, 1994, 1995 Free Software Foundation, Inc.
  4.  
  5. ;; Author: Joe Wells <jbw@bigbird.bu.edu>
  6. ;; Rewritten: Daniel.Pfeiffer@Informatik.START.dbp.de, fax (+49 69) 7588-2389
  7. ;; Keywords: help
  8.  
  9. ;; This file is part of GNU Emacs.
  10.  
  11. ;; GNU Emacs is free software; you can redistribute it and/or modify
  12. ;; it under the terms of the GNU General Public License as published by
  13. ;; the Free Software Foundation; either version 2, or (at your option)
  14. ;; any later version.
  15.  
  16. ;; GNU Emacs is distributed in the hope that it will be useful,
  17. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19. ;; GNU General Public License for more details.
  20.  
  21. ;; You should have received a copy of the GNU General Public License
  22. ;; along with GNU Emacs; see the file COPYING.  If not, write to the
  23. ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  24. ;; Boston, MA 02111-1307, USA.
  25.  
  26. ;;; Commentary:
  27.  
  28. ;; The ideas for this package were derived from the C code in
  29. ;; src/keymap.c and elsewhere.  The functions in this file should
  30. ;; always be byte-compiled for speed.  Someone should rewrite this in
  31. ;; C (as part of src/keymap.c) for speed.
  32.  
  33. ;; The idea for super-apropos is based on the original implementation
  34. ;; by Lynn Slater <lrs@esl.com>.
  35.  
  36. ;; History:
  37. ;; Fixed bug, current-local-map can return nil.
  38. ;; Change, doesn't calculate key-bindings unless needed.
  39. ;; Added super-apropos capability, changed print functions.
  40. ;;; Made fast-apropos and super-apropos share code.
  41. ;;; Sped up fast-apropos again.
  42. ;; Added apropos-do-all option.
  43. ;;; Added fast-command-apropos.
  44. ;; Changed doc strings to comments for helping functions.
  45. ;;; Made doc file buffer read-only, buried it.
  46. ;; Only call substitute-command-keys if do-all set.
  47.  
  48. ;; Optionally use configurable faces to make the output more legible.
  49. ;; Differentiate between command, function and macro.
  50. ;; Apropos-command (ex command-apropos) does cmd and optionally user var.
  51. ;; Apropos shows all 3 aspects of symbols (fn, var and plist)
  52. ;; Apropos-documentation (ex super-apropos) now finds all it should.
  53. ;; New apropos-value snoops through all values and optionally plists.
  54. ;; Reading DOC file doesn't load nroff.
  55. ;; Added hypertext following of documentation, mouse-2 on variable gives value
  56. ;;   from buffer in active window.
  57.  
  58. ;;; Code:
  59.  
  60. ;; I see a degradation of maybe 10-20% only.
  61. (defvar apropos-do-all nil
  62.   "*Whether the apropos commands should do more.
  63. Slows them down more or less.  Set this non-nil if you have a fast machine.")
  64.  
  65.  
  66. (defvar apropos-symbol-face (if window-system 'bold)
  67.   "*Face for symbol name in apropos output or `nil'.  
  68. This looks good, but slows down the commands several times.")
  69.  
  70. (defvar apropos-keybinding-face (if window-system 'underline)
  71.   "*Face for keybinding display in apropos output or `nil'.  
  72. This looks good, but slows down the commands several times.")
  73.  
  74. (defvar apropos-label-face (if window-system 'italic)
  75.   "*Face for label (Command, Variable ...) in apropos output or `nil'.
  76. If this is `nil' no mouse highlighting occurs.
  77. This looks good, but slows down the commands several times.
  78. When this is a face name, as it is initially, it gets transformed to a
  79. text-property list for efficiency.")
  80.  
  81. (defvar apropos-property-face (if window-system 'bold-italic)
  82.   "*Face for property name in apropos output or `nil'.  
  83. This looks good, but slows down the commands several times.")
  84.  
  85. (defvar apropos-match-face (if window-system 'secondary-selection)
  86.   "*Face for matching part in apropos-documentation/value output or `nil'.  
  87. This looks good, but slows down the commands several times.")
  88.  
  89.  
  90. (defvar apropos-mode-map
  91.   (let ((map (make-sparse-keymap)))
  92.     (define-key map "\C-m" 'apropos-follow)
  93.     (define-key map [mouse-2] 'apropos-mouse-follow)
  94.     (define-key map [down-mouse-2] nil)
  95.     map)
  96.   "Keymap used in Apropos mode.")
  97.  
  98.  
  99. (defvar apropos-regexp nil
  100.   "Regexp used in current apropos run.")
  101.  
  102. (defvar apropos-files-scanned ()
  103.   "List of elc files already scanned in current run of `apropos-documentation'.")
  104.  
  105. (defvar apropos-accumulator ()
  106.   "Alist of symbols already found in current apropos run.")
  107.  
  108. (defvar apropos-item ()
  109.   "Current item in or for apropos-accumulator.")
  110.  
  111. (defun apropos-mode ()
  112.   "Major mode for following hyperlinks in output of apropos commands.
  113.  
  114. \\{apropos-mode-map}"
  115.   (interactive)
  116.   (kill-all-local-variables)
  117.   (use-local-map apropos-mode-map)
  118.   (setq major-mode 'apropos-mode
  119.     mode-name "Apropos"))
  120.  
  121.  
  122. ;; For auld lang syne:
  123. ;;;###autoload
  124. (fset 'command-apropos 'apropos-command)
  125. ;;;###autoload
  126. (defun apropos-command (apropos-regexp &optional do-all)
  127.   "Shows commands (interactively callable functions) that match REGEXP.
  128. With optional prefix ARG or if `apropos-do-all' is non-nil, also show
  129. variables."
  130.   (interactive (list (read-string (concat "Apropos command "
  131.                       (if (or current-prefix-arg
  132.                           apropos-do-all)
  133.                           "or variable ")
  134.                       "(regexp): "))
  135.              current-prefix-arg))
  136.   (let ((message
  137.      (let ((standard-output (get-buffer-create "*Apropos*")))
  138.        (print-help-return-message 'identity))))
  139.     (or do-all (setq do-all apropos-do-all))
  140.     (setq apropos-accumulator
  141.       (apropos-internal apropos-regexp
  142.                 (if do-all
  143.                 (lambda (symbol) (or (commandp symbol)
  144.                              (user-variable-p symbol)))
  145.                   'commandp)))
  146.     (if (apropos-print
  147.      t
  148.      (lambda (p)
  149.        (let (doc symbol)
  150.          (while p
  151.            (setcar p (list
  152.               (setq symbol (car p))
  153.               (if (commandp symbol)
  154.                   (if (setq doc (documentation symbol t))
  155.                   (substring doc 0 (string-match "\n" doc))
  156.                 "(not documented)"))
  157.               (and do-all
  158.                    (user-variable-p symbol)
  159.                    (if (setq doc (documentation-property
  160.                           symbol 'variable-documentation t))
  161.                    (substring doc 0
  162.                           (string-match "\n" doc))))))
  163.            (setq p (cdr p)))))
  164.      nil)
  165.     (and message (message message)))))
  166.  
  167.  
  168. ;;;###autoload
  169. (defun apropos (apropos-regexp &optional do-all)
  170.   "Show all bound symbols whose names match REGEXP.
  171. With optional prefix ARG or if `apropos-do-all' is non-nil, also show unbound
  172. symbols and key bindings, which is a little more time-consuming.
  173. Returns list of symbols and documentation found."
  174.   (interactive "sApropos symbol (regexp): \nP")
  175.   (setq apropos-accumulator
  176.     (apropos-internal apropos-regexp
  177.               (and (not do-all)
  178.                    (not apropos-do-all)
  179.                    (lambda (symbol)
  180.                  (or (fboundp symbol)
  181.                      (boundp symbol)
  182.                      (symbol-plist symbol))))))
  183.   (apropos-print
  184.    (or do-all apropos-do-all)
  185.    (lambda (p)
  186.      (let (symbol doc)
  187.        (while p
  188.      (setcar p (list
  189.             (setq symbol (car p))
  190.             (if (fboundp symbol)
  191.             (if (setq doc (documentation symbol t))
  192.                 (substring doc 0 (string-match "\n" doc))
  193.               "(not documented)"))
  194.             (if (boundp symbol)
  195.             (if (setq doc (documentation-property
  196.                        symbol 'variable-documentation t))
  197.                 (substring doc 0
  198.                        (string-match "\n" doc))
  199.               "(not documented)"))
  200.             (if (setq doc (symbol-plist symbol))
  201.             (if (eq (/ (length doc) 2) 1)
  202.                 (format "1 property (%s)" (car doc))
  203.               (concat (/ (length doc) 2) " properties")))))
  204.      (setq p (cdr p)))))
  205.    nil))
  206.  
  207.  
  208. ;;;###autoload
  209. (defun apropos-value (apropos-regexp &optional do-all)
  210.   "Show all symbols whose value's printed image matches REGEXP.
  211. With optional prefix ARG or if `apropos-do-all' is non-nil, also looks
  212. at the function and at the names and values of properties.
  213. Returns list of symbols and values found."
  214.   (interactive "sApropos value (regexp): \nP")
  215.   (or do-all (setq do-all apropos-do-all))
  216.   (setq apropos-accumulator ())
  217.    (let (f v p)
  218.      (mapatoms
  219.       (lambda (symbol)
  220.     (setq f nil v nil p nil)
  221.     (or (memq symbol '(apropos-regexp do-all apropos-accumulator
  222.                       symbol f v p))
  223.         (setq v (apropos-value-internal 'boundp symbol 'symbol-value)))
  224.     (if do-all
  225.         (setq f (apropos-value-internal 'fboundp symbol 'symbol-function)
  226.           p (apropos-format-plist symbol "\n    " t)))
  227.     (if (or f v p)
  228.         (setq apropos-accumulator (cons (list symbol f v p)
  229.                         apropos-accumulator))))))
  230.   (apropos-print nil nil t))
  231.  
  232.  
  233. ;;;###autoload
  234. (defun apropos-documentation (apropos-regexp &optional do-all)
  235.   "Show symbols whose documentation contain matches for REGEXP.
  236. With optional prefix ARG or if `apropos-do-all' is non-nil, also use
  237. documentation that is not stored in the documentation file and show key
  238. bindings.
  239. Returns list of symbols and documentation found."
  240.   (interactive "sApropos documentation (regexp): \nP")
  241.   (or do-all (setq do-all apropos-do-all))
  242.   (setq apropos-accumulator () apropos-files-scanned ())
  243.   (let ((standard-input (get-buffer-create " apropos-temp"))
  244.     f v)
  245.     (unwind-protect
  246.     (save-excursion
  247.       (set-buffer standard-input)
  248.       (apropos-documentation-check-doc-file)
  249.       (if do-all
  250.           (mapatoms
  251.            (lambda (symbol)
  252.          (setq f (apropos-safe-documentation symbol)
  253.                v (get symbol 'variable-documentation))
  254.          (if (integerp v) (setq v))
  255.          (setq f (apropos-documentation-internal f)
  256.                v (apropos-documentation-internal v))
  257.          (if (or f v)
  258.              (if (setq apropos-item
  259.                    (cdr (assq symbol apropos-accumulator)))
  260.              (progn
  261.                (if f
  262.                    (setcar apropos-item f))
  263.                (if v
  264.                    (setcar (cdr apropos-item) v)))
  265.                (setq apropos-accumulator
  266.                  (cons (list symbol f v)
  267.                    apropos-accumulator)))))))
  268.       (apropos-print nil nil t))
  269.       (kill-buffer standard-input))))
  270.  
  271.  
  272. (defun apropos-value-internal (predicate symbol function)
  273.   (if (funcall predicate symbol)
  274.       (progn
  275.     (setq symbol (prin1-to-string (funcall function symbol)))
  276.     (if (string-match apropos-regexp symbol)
  277.         (progn
  278.           (if apropos-match-face
  279.           (put-text-property (match-beginning 0) (match-end 0)
  280.                      'face apropos-match-face
  281.                      symbol))
  282.           symbol)))))
  283.  
  284. (defun apropos-documentation-internal (doc)
  285.   (if (consp doc)
  286.       (apropos-documentation-check-elc-file (car doc))
  287.     (and doc
  288.      (string-match apropos-regexp doc)
  289.      (progn
  290.        (if apropos-match-face
  291.            (put-text-property (match-beginning 0)
  292.                   (match-end 0)
  293.                   'face apropos-match-face
  294.                   (setq doc (copy-sequence doc))))
  295.        doc))))
  296.  
  297. (defun apropos-format-plist (pl sep &optional compare)
  298.   (setq pl (symbol-plist pl))
  299.   (let (p p-out)
  300.     (while pl
  301.       (setq p (format "%s %S" (car pl) (nth 1 pl)))
  302.       (if (or (not compare) (string-match apropos-regexp p))
  303.       (if apropos-property-face
  304.           (put-text-property 0 (length (symbol-name (car pl)))
  305.                  'face apropos-property-face p))
  306.     (setq p nil))
  307.       (if p
  308.       (progn
  309.         (and compare apropos-match-face
  310.          (put-text-property (match-beginning 0) (match-end 0)
  311.                     'face apropos-match-face
  312.                     p))
  313.         (setq p-out (concat p-out (if p-out sep) p))))
  314.       (setq pl (nthcdr 2 pl)))
  315.     p-out))
  316.  
  317.  
  318. ;; Finds all documentation related to APROPOS-REGEXP in internal-doc-file-name.
  319.  
  320. (defun apropos-documentation-check-doc-file ()
  321.   (let (type symbol (sepa 2) sepb beg end)
  322.     (insert ?\^_)
  323.     (backward-char)
  324.     (insert-file-contents (concat doc-directory internal-doc-file-name))
  325.     (forward-char)
  326.     (while (save-excursion
  327.          (setq sepb (search-forward "\^_"))
  328.          (not (eobp)))
  329.       (beginning-of-line 2)
  330.       (if (save-restriction
  331.         (narrow-to-region (point) (1- sepb))
  332.         (re-search-forward apropos-regexp nil t))
  333.       (progn
  334.         (setq beg (match-beginning 0)
  335.           end (point))
  336.         (goto-char (1+ sepa))
  337.         (or (setq type (if (eq ?F (preceding-char))
  338.                    1    ; function documentation
  339.                  2)        ; variable documentation
  340.               symbol (read)
  341.               beg (- beg (point) 1)
  342.               end (- end (point) 1)
  343.               doc (buffer-substring (1+ (point)) (1- sepb))
  344.               apropos-item (assq symbol apropos-accumulator))
  345.         (setq apropos-item (list symbol nil nil)
  346.               apropos-accumulator (cons apropos-item
  347.                         apropos-accumulator)))
  348.         (if apropos-match-face
  349.         (put-text-property beg end 'face apropos-match-face doc))
  350.         (setcar (nthcdr type apropos-item) doc)))
  351.       (setq sepa (goto-char sepb)))))
  352.  
  353. (defun apropos-documentation-check-elc-file (file)
  354.   (if (member file apropos-files-scanned)
  355.       nil
  356.     (let (symbol doc beg end this-is-a-variable)
  357.       (setq apropos-files-scanned (cons file apropos-files-scanned))
  358.       (erase-buffer)
  359.       (insert-file-contents file)
  360.       (while (search-forward "\n#@" nil t)
  361.     ;; Read the comment length, and advance over it.
  362.     (setq end (read)
  363.           beg (1+ (point))
  364.           end (+ (point) end -1))
  365.     (forward-char)
  366.     (if (save-restriction
  367.           ;; match ^ and $ relative to doc string
  368.           (narrow-to-region beg end)
  369.           (re-search-forward apropos-regexp nil t))
  370.         (progn
  371.           (goto-char (+ end 2))
  372.           (setq doc (buffer-substring beg end)
  373.             end (- (match-end 0) beg)
  374.             beg (- (match-beginning 0) beg)
  375.             this-is-a-variable (looking-at "(def\\(var\\|const\\) ")
  376.             symbol (progn
  377.                  (skip-chars-forward "(a-z")
  378.                  (forward-char)
  379.                  (read))
  380.             symbol (if (consp symbol)
  381.                    (nth 1 symbol)
  382.                  symbol))
  383.           (if (if this-is-a-variable
  384.               (get symbol 'variable-documentation)
  385.             (and (fboundp symbol) (apropos-safe-documentation symbol)))
  386.           (progn
  387.             (or (setq apropos-item (assq symbol apropos-accumulator))
  388.             (setq apropos-item (list symbol nil nil)
  389.                   apropos-accumulator (cons apropos-item
  390.                             apropos-accumulator)))
  391.             (if apropos-match-face
  392.             (put-text-property beg end 'face apropos-match-face
  393.                        doc))
  394.             (setcar (nthcdr (if this-is-a-variable 2 1)
  395.                     apropos-item)
  396.                 doc)))))))))
  397.  
  398.  
  399.  
  400. (defun apropos-safe-documentation (function)
  401.   "Like documentation, except it avoids calling `get_doc_string'.
  402. Will return nil instead."
  403.   (while (and function (symbolp function))
  404.     (setq function (if (fboundp function)
  405.                (symbol-function function))))
  406.   (if (eq (car-safe function) 'macro)
  407.       (setq function (cdr function)))
  408.   (setq function (if (byte-code-function-p function)
  409.              (if (> (length function) 4)
  410.              (aref function 4))
  411.            (if (eq (car-safe function) 'autoload)
  412.                (nth 2 function)
  413.              (if (eq (car-safe function) 'lambda)
  414.              (if (stringp (nth 2 function))
  415.                  (nth 2 function)
  416.                (if (stringp (nth 3 function))
  417.                    (nth 3 function)))))))
  418.   (if (integerp function)
  419.       nil
  420.     function))
  421.  
  422.  
  423.  
  424. (defun apropos-print (do-keys doc-fn spacing)
  425.   "Output result of various apropos commands with `apropos-regexp'.
  426. APROPOS-ACCUMULATOR is a list.  Optional DOC-FN is called for each element
  427. of apropos-accumulator and may modify it resulting in (symbol fn-doc
  428. var-doc [plist-doc]).  Returns sorted list of symbols and documentation
  429. found."
  430.   (if (null apropos-accumulator)
  431.       (message "No apropos matches for `%s'" apropos-regexp)
  432.     (if doc-fn
  433.     (funcall doc-fn apropos-accumulator))
  434.     (setq apropos-accumulator
  435.       (sort apropos-accumulator (lambda (a b)
  436.                       (string-lessp (car a) (car b)))))
  437.     (and apropos-label-face
  438.      (symbolp apropos-label-face)
  439.      (setq apropos-label-face `(face ,apropos-label-face
  440.                      mouse-face highlight)))
  441.     (with-output-to-temp-buffer "*Apropos*"
  442.       (let ((p apropos-accumulator)
  443.         (old-buffer (current-buffer))
  444.         symbol item point1 point2)
  445.     (set-buffer standard-output)
  446.     (apropos-mode)
  447.     (if window-system
  448.         (insert "If you move the mouse over text that changes color,\n"
  449.             (substitute-command-keys
  450.              "you can click \\[apropos-mouse-follow] to get more information.\n")))
  451.     (insert (substitute-command-keys
  452.          "In this buffer, type \\[apropos-follow] to get full documentation.\n\n"))
  453.     (while (consp p)
  454.       (or (not spacing) (bobp) (terpri))
  455.       (setq apropos-item (car p)
  456.         symbol (car apropos-item)
  457.         p (cdr p)
  458.         point1 (point))
  459.       (princ symbol)                ; print symbol name
  460.       (setq point2 (point))
  461.       ;; Calculate key-bindings if we want them.
  462.       (and do-keys
  463.            (commandp symbol)
  464.            (indent-to 30 1)
  465.            (if (let ((keys
  466.               (save-excursion
  467.                 (set-buffer old-buffer)
  468.                 (where-is-internal symbol)))
  469.              filtered)
  470.              ;; Copy over the list of key sequences,
  471.              ;; omitting any that contain a buffer or a frame.
  472.              (while keys
  473.                (let ((key (car keys))
  474.                  (i 0)
  475.                  loser)
  476.              (while (< i (length key))
  477.                (if (or (framep (aref key i))
  478.                    (bufferp (aref key i)))
  479.                    (setq loser t))
  480.                (setq i (1+ i)))
  481.              (or loser
  482.                  (setq filtered (cons key filtered))))
  483.                (setq keys (cdr keys)))
  484.              (setq item filtered))
  485.            ;; Convert the remaining keys to a string and insert.
  486.            (insert
  487.             (mapconcat
  488.              (lambda (key)
  489.                (setq key (key-description key))
  490.                (if apropos-keybinding-face
  491.                (put-text-property 0 (length key)
  492.                           'face apropos-keybinding-face
  493.                           key))
  494.                key)
  495.              item ", "))
  496.          (insert "Type ")
  497.          (insert "M-x")
  498.          (put-text-property (- (point) 3) (point)
  499.                     'face apropos-keybinding-face)
  500.          (insert " " (symbol-name symbol) " ")
  501.          (insert "RET")
  502.          (put-text-property (- (point) 3) (point)
  503.                     'face apropos-keybinding-face)))
  504.       (terpri)
  505.       ;; only now so we don't propagate text attributes all over
  506.       (put-text-property point1 point2 'item
  507.                  (if (eval `(or ,@(cdr apropos-item)))
  508.                  (car apropos-item)
  509.                    apropos-item))
  510.       (if apropos-symbol-face
  511.           (put-text-property point1 point2 'face apropos-symbol-face))
  512.       (apropos-print-doc 'describe-function 1
  513.                  (if (commandp symbol)
  514.                  "Command"
  515.                    (if (apropos-macrop symbol)
  516.                    "Macro"
  517.                  "Function"))
  518.                  do-keys)
  519.       (apropos-print-doc 'describe-variable 2
  520.                  "Variable" do-keys)
  521.       (apropos-print-doc 'apropos-describe-plist 3
  522.                  "Plist" nil)))))
  523.   (prog1 apropos-accumulator
  524.     (setq apropos-accumulator ())))    ; permit gc
  525.  
  526.  
  527. (defun apropos-macrop (symbol)
  528.   "T if SYMBOL is a Lisp macro."
  529.   (and (fboundp symbol)
  530.        (consp (setq symbol
  531.             (symbol-function symbol)))
  532.        (or (eq (car symbol) 'macro)
  533.        (if (eq (car symbol) 'autoload)
  534.            (memq (nth 4 symbol)
  535.              '(macro t))))))
  536.  
  537.  
  538. (defun apropos-print-doc (action i str do-keys)
  539.   (if (stringp (setq i (nth i apropos-item)))
  540.       (progn
  541.     (insert "  ")
  542.     (put-text-property (- (point) 2) (1- (point))
  543.                'action action)
  544.     (insert str ": ")
  545.     (if apropos-label-face
  546.         (add-text-properties (- (point) (length str) 2)
  547.                  (1- (point))
  548.                  apropos-label-face))
  549.     (insert (if do-keys (substitute-command-keys i) i))
  550.     (or (bolp) (terpri)))))
  551.  
  552.  
  553. (defun apropos-mouse-follow (event)
  554.   (interactive "e")
  555.   (let ((other (if (eq (current-buffer) (get-buffer "*Apropos*"))
  556.            ()
  557.          (current-buffer))))
  558.     (save-excursion
  559.       (set-buffer (window-buffer (posn-window (event-start event))))
  560.       (goto-char (posn-point (event-start event)))
  561.       (or (and (not (eobp)) (get-text-property (point) 'mouse-face))
  562.       (and (not (bobp)) (get-text-property (1- (point)) 'mouse-face))
  563.       (error "There is nothing to follow here"))
  564.       (apropos-follow other))))
  565.  
  566.  
  567. (defun apropos-follow (&optional other)
  568.   (interactive)
  569.   (let* (;; Properties are always found at the beginning of the line.
  570.      (bol (save-excursion (beginning-of-line) (point)))
  571.      ;; If there is no `item' property here, look behind us.
  572.      (item (get-text-property bol 'item))
  573.      (item-at (if item nil (previous-single-property-change bol 'item)))
  574.      ;; Likewise, if there is no `action' property here, look in front.
  575.      (action (get-text-property bol 'action))
  576.      (action-at (if action nil (next-single-property-change bol 'action))))
  577.     (and (null item) item-at
  578.      (setq item (get-text-property (1- item-at) 'item)))
  579.     (and (null action) action-at
  580.      (setq action (get-text-property action-at 'action)))
  581.     (if (not (and item action))
  582.     (error "There is nothing to follow here"))
  583.     (if (consp item) (error "There is nothing to follow in `%s'" (car item)))
  584.     (if other (set-buffer other))
  585.     (funcall action item)))
  586.  
  587.  
  588.  
  589. (defun apropos-describe-plist (symbol)
  590.   "Display a pretty listing of SYMBOL's plist."
  591.   (with-output-to-temp-buffer "*Help*"
  592.     (set-buffer standard-output)
  593.     (princ "Symbol ")
  594.     (prin1 symbol)
  595.     (princ "'s plist is\n (")
  596.     (if apropos-symbol-face
  597.     (put-text-property 8 (- (point) 14) 'face apropos-symbol-face))
  598.     (insert (apropos-format-plist symbol "\n  "))
  599.     (princ ")")
  600.     (print-help-return-message)))
  601.  
  602. ;;; apropos.el ends here
  603.